﻿using System;
using System.Collections.Generic;
using System.Text;
using XCore.Logger;
using XCore.Extensions;
using System.Linq;
using XCore.Dapper;
using XCore.Encryption;
using System.Data;
using SaaS.Model.Entity.Sites;
using XCore.Dependency;
using SaaS.Model.Entity.Auths;
using SaaS.Core;
using SaaS.Model.Entity.Users;
using SaaS.Cache.Users;
using System.Text.RegularExpressions;
using SaaS.Model.Dto.Users;
using XCore.Web.Jwt;
using SaaS.Cache.Auths;
using SaaS.Model.Enums;

namespace Web.Client.Services.Users
{
    public class UserAppService : ClientApplicationServiceBase, ISingletonDependency
    {
        private readonly UserCacheService _userCacheService;
        private readonly UserAuthCacheService _userAuthCacheService;
        public UserAppService(UserCacheService userCacheService, UserAuthCacheService userAuthCacheService)
        {
            _userCacheService = userCacheService;
            _userAuthCacheService = userAuthCacheService;
        }
        #region ===============公共对外方法====================

        /// <summary>
        /// 获取用户信息（先从缓存读）
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public UserModel GetUserInfo(int id)
        {
            UserModel user = _userCacheService.GetUserInfo(id);
            if (!user)
            {
                user = SCC.Users.FirstOrDefault(c => c.Id == id);
                _userCacheService.SaveUserInfo(user);
            }
            return user;
        }
        /// <summary>
        /// 注册，并返回token自动登录
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public JWTResult Registered(string username, string password)
        {
            User user = new User
            {
                UserName = username,
                Password = password
            };
            this.CheckUser(user);
            string secretkey = MD5Encryption.MD5Salt();
            this.CreateTenant(user, secretkey);
            string token = JWTHelper.CreateToken(new JWTOptions(CoreSetting.Audience, CoreSetting.Issuer, CoreSetting.Expire), user.Id);
            _userAuthCacheService.SetUserToken(user.Id, token);
            return new JWTResult(token, CoreSetting.Expire);
        }
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public JWTResult Login(string username, string password)
        {
            var user = SCC.Users.Where(c => c.UserName == username).Select(c => new { c.Id, c.Password }).FirstOrDefault();
            if (user == null) throw new ClientException("用户名不存在", ClientLoggerSource.LOGIN_REGISTER);
            if (user.Password.IsEqual(MD5Encryption.Encryption(password))) throw new ClientException("密码不正确", ClientLoggerSource.LOGIN_REGISTER);
            string token = JWTHelper.CreateToken(new JWTOptions(CoreSetting.Audience, CoreSetting.Issuer, CoreSetting.Expire), user.Id);
            _userAuthCacheService.SetUserToken(user.Id, token);
            return new JWTResult(token, CoreSetting.Expire);
        }
        /// <summary>
        /// 上传用户头像
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="avatar"></param>
        /// <returns></returns>
        public bool UploadAvatar(int userId, string avatar)
        {
            if (!SCC.Users.Any(c => c.Id == userId)) throw new MessageException(CoreSetting.Error_ID);
            return Repository.Update<SystemAdmin, string>(userId, c => c.Avatar, avatar);
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="id"></param>
        /// <param name="password"></param>
        public bool ResetPwd(int id, string password)
        {
            if (string.IsNullOrWhiteSpace(password)) throw new ClientException("密码不能为空", ClientLoggerSource.USER_ERROR);
            var user = SCC.Users.FirstOrDefault(c => c.Id == id);
            if (user == null) throw new MessageException("用户不存在");
            password = MD5Encryption.Encryption(password);
            return Repository.Update<User, string>(id, c => c.Password, password) && Logger.Log("修改密码");
        }


        #endregion

        #region ==============私有方法==================

        /// <summary>
        /// 检查用户实体
        /// </summary>
        /// <param name="user"></param>
        private void CheckUser(User user)
        {
            this.CheckUserName(user.UserName);
            this.CheckPassword(user.Password);
            if (SCC.Users.Any(c => c.UserName == user.UserName)) throw new ClientException("用户名存在", ClientLoggerSource.LOGIN_REGISTER);
        }
        /// <summary>
        /// 检查用户名
        /// </summary>
        /// <param name="username"></param>
        private void CheckUserName(string username)
        {
            if (string.IsNullOrWhiteSpace(username)) throw new ClientException("用户名不能为空", ClientLoggerSource.LOGIN_REGISTER);
            if (!Regex.IsMatch(username, "[A-Za-z0-9]{5,32}")) throw new ClientException("用户名由字母、数字组成，长度不能少于5个字符", ClientLoggerSource.LOGIN_REGISTER);
        }
        /// <summary>
        /// 检查密码
        /// </summary>
        /// <param name="password"></param>
        private void CheckPassword(string password)
        {
            if (string.IsNullOrWhiteSpace(password)) throw new ClientException("密码不能为空", ClientLoggerSource.LOGIN_REGISTER);
            if (!(password.Length >= 6 && password.Length < 32)) throw new ClientException("密码长度为6~32个字符", ClientLoggerSource.LOGIN_REGISTER);
        }

        /// <summary>
        /// 注册通用方法
        /// </summary>
        /// <param name="user">用户</param>
        /// <param name="secretkey">秘钥</param>
        /// <returns></returns>
        private void CreateTenant(User user, string secretkey)
        {
            //注册，指定租户连接字符串
            using (IDapperDatabase db = CreateDapperDatabase(IsolationLevel.ReadUncommitted))
            {
                //# 创建会员
                user.Password = PwdEncryption.Encryption(user.Password);
                int userId = db.InsertAndGetId(user);

                //# 创建租户
                Site tenant = new Site
                {
                    SecretKey = secretkey,
                    Name = user.UserName,
                    Domain = user.UserName
                };
                int tenantId = db.InsertAndGetId(tenant);
                //# 关联会员与租户关系
                UserTenant userTenant = new UserTenant
                {
                    Id = userId,
                    TenantId = tenantId
                };
                db.Insert(userTenant);
                //# 创建站点管理员
                SiteAdmin admin = new SiteAdmin
                {
                    UserName = CoreSetting.DefaultAdminName,
                    SiteId = tenantId,
                    IsDefault = true,
                    Password = PwdEncryption.Encryption(CoreSetting.DefaultPassword, secretkey)
                };

                db.CommitRollback(() =>
                {
                    UserModel model = user;
                    model.Tenants = new int[] { tenantId };
                    _userCacheService.SaveUserInfo(user);
                });
                db.Commit();
            }
        }
        #endregion
    }
}
